package com.treeman.api.controller.marker;

import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.google.gson.Gson;
import com.treeman.api.ApiRequestError;
import com.treeman.api.ApiRequestError.ApiError;
import com.treeman.api.controller.ApiExceptionResolverController;
import com.treeman.api.json.marker.MarkerJson;
import com.treeman.marker.exception.MarkerNotFoundException;
import com.treeman.marker.exception.NoMarkersFoundException;
import com.treeman.marker.service.MarkerService;
import com.treeman.user.exception.UserNotLoggedException;

@Controller
@RequestMapping(value = "/api/me")
@PreAuthorize("isAuthenticated()")
public class CurrentUserMarkerDataController extends
		ApiExceptionResolverController {

	private static Logger log = Logger
			.getLogger(CurrentUserMarkerDataController.class);

	@Autowired
	private MarkerService markerService;

	@RequestMapping(value = "/markers", method = RequestMethod.POST)
	@ResponseStatus(value = HttpStatus.OK)
	public @ResponseBody
	MarkerJson addMarker(
			@RequestParam(value = "name", required = true) String name,
			@RequestParam(value = "description", required = false) String description,
			@RequestParam(value = "address", required = false) String address,
			@RequestParam(value = "longitude", required = true) Double longitude,
			@RequestParam(value = "latitude", required = true) Double latitude,
			@RequestParam(value = "type", required = true) String type) {

		String username = SecurityContextHolder.getContext()
				.getAuthentication().getName();

		MarkerJson marker = new MarkerJson(null, name, address, description,
				longitude, latitude, type, username);
		Long markerId = markerService.addMarker(marker);
		marker.setId(markerId);
		log.debug("Marker added successfully. Sending id: " + markerId);
		return marker;
	}

	@RequestMapping(value = "/markers", method = RequestMethod.GET)
	public @ResponseBody
	List<MarkerJson> getMarkers() throws NoMarkersFoundException {

		String username = SecurityContextHolder.getContext()
				.getAuthentication().getName();

		List<MarkerJson> markers = markerService.getUserMarkersJson(username);
		log.debug("Sending back markers. Count: " + markers.size());
		return markers;
	}

	@RequestMapping(value = "/markers/{id}", method = RequestMethod.GET)
	public @ResponseBody
	MarkerJson getMarkerById(@PathVariable Long id)
			throws MarkerNotFoundException {
		log.debug("Getting marker by id: " + id);
		return markerService.getMarkerJsonById(id);
	}

	@RequestMapping(value = "/markers/{id}", method = RequestMethod.PUT)
	public @ResponseBody
	Long updateMarker(@RequestParam(value = "marker") String markerJson,
			@PathVariable Long id) throws MarkerNotFoundException {
		Gson gson = new Gson();
		MarkerJson marker = gson.fromJson(markerJson, MarkerJson.class);

		log.debug("Updating marker. Id: " + marker.getId());
		marker.setId(id);

		String username = SecurityContextHolder.getContext()
				.getAuthentication().getName();

		Long updatedMarkerId = markerService.updateMarkerJson(marker, username);

		return updatedMarkerId;
	}

	@RequestMapping(value = "/markers/{id}", method = RequestMethod.DELETE)
	public @ResponseBody
	void deleteMarker(@PathVariable Long id) throws UserNotLoggedException,
			MarkerNotFoundException {
		String username = SecurityContextHolder.getContext()
				.getAuthentication().getName();

		log.debug("Deleting marker. Id=" + id + " user=" + username);
		markerService.deleteMarker(id, username);
	}

	/* EXCEPTIONS */

	@ExceptionHandler(NoMarkersFoundException.class)
	@ResponseStatus(value = HttpStatus.NOT_FOUND)
	public @ResponseBody
	ApiRequestError handleNoMarkersFoundException(NoMarkersFoundException e) {
		log.warn("There is no markers for user: " + e.getAuthor());

		return new ApiRequestError(ApiError.NOT_FOUND,
				"User doesn not have any markers.");
	}

	@ExceptionHandler(MarkerNotFoundException.class)
	@ResponseStatus(value = HttpStatus.NOT_FOUND)
	public @ResponseBody
	ApiRequestError handleMarkerNotFoundException(MarkerNotFoundException e) {
		log.warn("No marker with id: " + e.getMarkerId());

		return new ApiRequestError(ApiError.NOT_FOUND,
				"No marker with specified id.");
	}
}
